<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>QeePHP 快速入门</title>
<link href="css/base.css" rel="stylesheet" type="text/css">
</head>
<body>

<div id="page">


<div class="guide-section">

  <div class="guide-header">
    <span class="nav">
      <a href="http://qee13.com/app/?action=docs">文档索引</a>
      &raquo;
      <a href="index.html">QeePHP 快速入门</a>
      &raquo;
      <a href="node-tasks.html">实现任务管理</a>
      &raquo;
      修改和删除任务    </span>
  </div>

  <div class="guide-section-details formatted">
    
<h1>修改和删除任务</h1>

<p>修改工作非常简单，在 tasks
控制器中添加如下代码即可：</p>

<pre class="php code"><span class="kw2">function</span> actionEdit<span
class="br0">&#40;</span><span class="br0">&#41;</span>
<span
class="br0">&#123;</span>
        <span class="re0">$user</span><span
class="sy0">=</span><span class="re0">$this</span><span
class="sy0">-&gt;</span>_app<span class="sy0">-&gt;</span><span
class="me1">currentUserObject</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
        <span
class="co1">// 查询指定 ID，并且其所有者是当前用户的任务（禁止修改他人的任务），注意getOne会一直返回Task对象，如果不存在会返回新的Task对象</span>
        <span
class="re0">$task</span><span class="sy0">=</span>Task<span
class="sy0">::</span><span class="me2">find</span><span
class="br0">&#40;</span><span
class="st_h">'task_id =? and owner_id =?'</span><span
class="sy0">,</span>request<span class="br0">&#40;</span><span
class="st_h">'task_id'</span><span class="br0">&#41;</span><span
class="sy0">,</span><span class="re0">$user</span><span
class="sy0">-&gt;</span><span class="me1">id</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">-&gt;</span><span
class="me1">getOne</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span
class="co1">// 如果任务的不存在，视图修改的任务不存在或者不是当前用户创建的</span>
        <span
class="kw1">if</span> <span class="br0">&#40;</span><span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">isNewRecord</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="br0">&#123;</span>
                <span class="kw1">return</span> <span
class="re0">$this</span><span class="sy0">-&gt;</span>_redirectMessage<span
class="br0">&#40;</span><span class="st_h">'对不起'</span><span
class="sy0">,</span> <span
class="st_h">'任务不存在或已被删除'</span><span
class="sy0">,</span> url<span class="br0">&#40;</span><span
class="st_h">'tasks/index'</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
        <span
class="br0">&#125;</span>
        <span class="kw1">if</span> <span
class="br0">&#40;</span>request_is_post<span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="br0">&#123;</span>
                <span
class="co1">// 直接通过表单赋值</span>
                <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">changeProps</span><span class="br0">&#40;</span><span
class="re0">$_POST</span><span class="br0">&#41;</span><span
class="sy0">;</span>
                <span
class="co1">// 根据是否选中“已完成”检查框来设置任务的状态</span>
        <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">completed</span><span class="br0">&#40;</span>request<span
class="br0">&#40;</span><span class="st_h">'is_completed'</span><span
class="sy0">,</span><span class="kw2">false</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
&nbsp;
        <span
class="co1">// 保存并重定向浏览器</span>
        <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">save</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
                <span
class="kw1">return</span> <span class="re0">$this</span><span
class="sy0">-&gt;</span>_redirect<span class="br0">&#40;</span>url<span
class="br0">&#40;</span><span class="st_h">'tasks/index'</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
        <span class="br0">&#125;</span>
        <span
class="re0">$this</span><span class="sy0">-&gt;</span>_view<span
class="br0">&#91;</span><span class="st_h">'task'</span><span
class="br0">&#93;</span><span class="sy0">=</span><span
class="re0">$task</span><span class="sy0">;</span>
<span
class="br0">&#125;</span></pre>

<p>这个方法完成下列工作：</p>

<ol>
	<li>首先根据指定的 task_id
	和当前用户ID查询任务对象，如果失败则重定向浏览器。这可以有效阻止用户尝试编辑不属于自己的任务。</li>

	<li>如果是 POST
	提交，则更新任务信息，并且根据是否选中了“已完成”检查框来修改任务状态。最后保存修改并重定向浏览器。</li>
</ol>

<p>上述代码中，之所以修改任务状态必须调用 completed()
方法，是为了因为 task 模型的 is_completed
属性非常重要，不应该“无意”中被修改。明确的 completed()
方法调用就可以避免此问题。而且当任务状态改变为“已完成”时，还需要设置任务的
completed_at 属性，以记录任务完成的时刻，completed()
方法可以同时完成这项修改。</p>

<p>所以我们还要在 task 模型中添加 completed() 方法：</p>

<pre class="php code"><span
class="co4">/**
 * 明确修改任务的状态
 * @param boolean $completed
 * @return Task
 */</span>
<span
class="kw2">function</span> completed<span class="br0">&#40;</span><span
class="re0">$completed</span><span class="br0">&#41;</span><span
class="br0">&#123;</span>
    <span class="re0">$completed</span> <span
class="sy0">=</span> <span class="br0">&#40;</span>bool<span
class="br0">&#41;</span><span class="re0">$completed</span><span
class="sy0">;</span>
    <span class="kw1">if</span> <span
class="br0">&#40;</span><span class="re0">$completed</span> <span
class="sy0">&amp;&amp;</span> <span class="sy0">!</span><span
class="re0">$this</span><span class="sy0">-&gt;</span><span
class="me1">is_completed</span><span class="br0">&#41;</span>
    <span
class="br0">&#123;</span>
            <span
class="co1">// 如果任务状态从“未完成”变成“已完成”，则保存完成任务的时刻</span>
            <span
class="co1">// changePropForce() 可以强制改变一个只读属性的值</span>
            <span
class="re0">$this</span><span class="sy0">-&gt;</span><span
class="me1">changePropForce</span><span class="br0">&#40;</span><span
class="st_h">'completed_at'</span><span class="sy0">,</span> <span
class="kw3">time</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
    <span class="br0">&#125;</span>
    <span
class="kw1">elseif</span> <span class="br0">&#40;</span><span
class="sy0">!</span><span class="re0">$completed</span><span
class="br0">&#41;</span>
    <span class="br0">&#123;</span>
            <span
class="co1">// 如果任务状态设置为“未完成”，则清理掉 completed_at 记录的时间</span>
            <span
class="re0">$this</span><span class="sy0">-&gt;</span><span
class="me1">changePropForce</span><span class="br0">&#40;</span><span
class="st_h">'completed_at'</span><span class="sy0">,</span> <span
class="kw2">null</span><span class="br0">&#41;</span><span
class="sy0">;</span>
    <span class="br0">&#125;</span>
    <span
class="re0">$this</span><span class="sy0">-&gt;</span><span
class="me1">changePropForce</span><span class="br0">&#40;</span><span
class="st_h">'is_completed'</span><span class="sy0">,</span> <span
class="re0">$completed</span><span class="br0">&#41;</span><span
class="sy0">;</span>
    <span class="kw1">return</span> <span
class="re0">$this</span><span class="sy0">;</span>
<span
class="br0">&#125;</span></pre>

<p>同时修改 _code/view/tasks/edit.php</p>

<pre class="php code"><span class="kw2">&lt;?PHP</span> <span
class="re0">$this</span><span class="sy0">-&gt;</span>_extends<span
class="br0">&#40;</span><span class="st_h">'_layouts/default_layout'</span><span
class="br0">&#41;</span><span class="sy0">;</span> <span
class="kw2">?&gt;</span>
<span class="kw2">&lt;?PHP</span> <span
class="re0">$this</span><span class="sy0">-&gt;</span>_block<span
class="br0">&#40;</span><span class="st_h">'contents'</span><span
class="br0">&#41;</span><span class="sy0">;</span>?<span
class="sy0">&gt;</span>
&lt;div&gt;
        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
        &lt;input type=&quot;hidden&quot; name=&quot;task_id&quot; value=&quot;<span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">id</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="kw2">?&gt;</span>&quot;&gt;
        <span
class="kw2">&lt;?php</span> <span class="kw1">if</span> <span
class="br0">&#40;</span><span class="sy0">!</span><span
class="kw3">empty</span><span class="br0">&#40;</span><span
class="re0">$errors</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">:</span><span
class="kw2">?&gt;</span>
        &lt;div class=&quot;alert&quot;&gt;
                <span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="re0">$errors</span>?<span
class="sy0">&gt;</span>
        &lt;/div&gt;
        <span
class="kw2">&lt;?php</span> <span class="kw1">endif</span><span
class="sy0">;</span>?<span
class="sy0">&gt;</span>
        &lt;fieldset&gt;
        &lt;legend&gt;编辑任务 - <span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">id</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span
class="kw2">?&gt;</span>&lt;/legend&gt;
        &lt;p&gt;
                &lt;label&gt;任务主题&lt;/label&gt;
                &lt;input name=&quot;subject&quot; value=&quot;<span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">subject</span>?<span
class="sy0">&gt;</span>&quot;&gt;
        &lt;/p&gt;
        &lt;p&gt;
                &lt;label&gt;任务描述&lt;/label&gt;
                &lt;textarea name=&quot;description&quot; style=&quot;width:400px;height: 100px;&quot;&gt;<span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">description</span>?<span
class="sy0">&gt;</span>&lt;/textarea&gt;
        &lt;/p&gt;
        &lt;p&gt;
                &lt;label&gt;
                &lt;input type=&quot;checkbox&quot; name=&quot;is_completed&quot; value=&quot;1&quot;&gt;
                完成
                &lt;/label&gt;
        &lt;/p&gt;
        &lt;p&gt;
                &lt;input type=&quot;submit&quot; value=&quot;提交&quot;&gt;
        &lt;/p&gt;
        &lt;/fieldset&gt;
        &lt;/form&gt;
&lt;/div&gt;
<span
class="kw2">&lt;?PHP</span> <span class="re0">$this</span><span
class="sy0">-&gt;</span>_endblock<span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">;</span>?<span
class="sy0">&gt;</span></pre>

<p>相比传统的做法，面向对象的方式在初期会需要更多的代码。但是这些代码保证了逻辑的严密性和数据的有效性，应用软件规模越大，这种做法带来的好处就越多。而且随着应用规模的逐渐增长，面向对象充分重用逻辑与代码的优势就会体现出来，最终可以获得一个更健壮、内部更整洁的系统。</p>

<p>实际运行效果：</p>

<div class="figure"><img src="images/tasks-edit-01.png" alt="" />
	<p>修改状态后的任务</p>
</div>

<h2>删除任务</h2>

<p>删除任务功能非常简单：</p>

<pre class="php code"><span class="kw2">function</span> actionDelete<span
class="br0">&#40;</span><span class="br0">&#41;</span>
<span
class="br0">&#123;</span>
        <span
class="co1">// destroyWhere() 方法的参数和 find() 方法完全一致</span>
        <span
class="re0">$user</span><span class="sy0">=</span><span
class="re0">$this</span><span class="sy0">-&gt;</span>_app<span
class="sy0">-&gt;</span><span class="me1">currentUserObject</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
        Task<span class="sy0">::</span><span
class="me2">meta</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">-&gt;</span><span
class="me1">destroyWhere</span><span class="br0">&#40;</span><span
class="st_h">'task_id = ? AND [owner.user_id] = ?'</span><span
class="sy0">,</span>request<span class="br0">&#40;</span><span
class="st_h">'task_id'</span><span class="br0">&#41;</span><span
class="sy0">,</span><span class="re0">$user</span><span
class="sy0">-&gt;</span><span class="me1">id</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span
class="kw1">return</span> <span class="re0">$this</span><span
class="sy0">-&gt;</span>_redirectMessage<span
class="br0">&#40;</span>
                <span
class="st_h">'删除成功'</span><span
class="sy0">,</span>
                <span
class="st_h">'您已经成功删除了一个任务'</span><span
class="sy0">,</span>
                url<span class="br0">&#40;</span><span
class="st_h">'tasks/index'</span><span class="br0">&#41;</span>
        <span
class="br0">&#41;</span><span class="sy0">;</span>
<span
class="br0">&#125;</span></pre>

<p>修改一下 _code/view/tasks/index.php
视图，将删除任务的连接加进去：</p>

<pre class="php code">&lt;p class=&quot;meta&quot;&gt;
  <span
class="kw2">&lt;?php</span> <span class="kw1">if</span> <span
class="br0">&#40;</span><span class="re0">$task</span><span
class="sy0">-&gt;</span><span class="me1">is_completed</span><span
class="br0">&#41;</span><span class="sy0">:</span> <span
class="kw2">?&gt;</span>
  &lt;em&gt;已经在 <span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="kw3">date</span><span class="br0">&#40;</span><span
class="st_h">'m-d H:i'</span><span class="sy0">,</span> <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">completed_at</span><span class="br0">&#41;</span><span
class="sy0">;</span> <span
class="kw2">?&gt;</span> 完成该任务&lt;/em&gt;
  <span
class="kw2">&lt;?php</span> <span class="kw1">else</span><span
class="sy0">:</span> <span
class="kw2">?&gt;</span>
  &lt;strong&gt;添加日期：<span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> <span
class="kw3">date</span><span class="br0">&#40;</span><span
class="st_h">'m-d H:i'</span><span class="sy0">,</span> <span
class="re0">$task</span><span class="sy0">-&gt;</span><span
class="me1">created</span><span class="br0">&#41;</span><span
class="sy0">;</span> <span class="kw2">?&gt;</span>&lt;/strong&gt;
  <span
class="kw2">&lt;?php</span> <span class="kw1">endif</span><span
class="sy0">;</span> <span class="kw2">?&gt;</span>
  , &lt;a href=&quot;<span
class="kw2">&lt;?php</span> <span class="kw3">echo</span> url<span
class="br0">&#40;</span><span class="st_h">'tasks/delete'</span><span
class="sy0">,</span> <span class="kw3">array</span><span
class="br0">&#40;</span><span class="st_h">'task_id'</span> <span
class="sy0">=&gt;</span> <span class="re0">$task</span><span
class="sy0">-&gt;</span><span class="me1">id</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="br0">&#41;</span><span
class="sy0">;</span> <span
class="kw2">?&gt;</span>&quot; onclick=&quot;return confirm('您确定要删除该任务吗?');&quot;&gt;删除&lt;/a&gt;
&lt;/p&gt;</pre>

<p>运行效果：</p>

<div class="figure"><img src="images/tasks-edit-02.png" alt="" />
	<p>删除提示</p>
</div>

<div class="figure"><img src="images/tasks-edit-03.png" alt="" />
	<p>成功删除</p>
</div>

<blockquote>
	<p>课后思考：大家不难发现，创建任务和编辑任务的View代码相差不大，重用性非常高，是否有好的办法可以将两个View合并为一个View？设置两个Action合并为一个Action？</p>
</blockquote>
$Id: tasks-edit.texy 2013-08-14 02:24:25Z Tim13 $
  </div>

  <div class="guide-footer">

    <table border="0" width="100%">
      <tr>
        <td align="left" width="200">
                    &laquo;
          <a href="node-tasks-add.html">添加任务</a>
          
        </td>

        <td align="center">
          本章：<a href="node-tasks.html">实现任务管理</a>
          <br />
          <a href="index.html">返回索引页</a>
        </td>

        <td align="right" width="200">
                    <a href="node-tasks-pagination.html">分页与最后的完善</a> 
          &raquo;
                  </td>
      </tr>
    </table>

  </div>

</div>


</div>

</body>
</html>


